#include "ConfManager.h"
#include "FileHandler.h"
#include "FileTypes.h"
#include "HttpResponse.h"


#include <fcntl.h>
#include <sys/stat.h>
#include <cstring>
// #include <iostream>

using namespace std;

FileHandler::FileHandler(string rootPath)
    : _rootPath(rootPath)
{ }

FileHandler::~FileHandler()
{ }

string FileHandler::GetRootPath()
{
    return _rootPath;
}

void FileHandler::Process(int sockfd, const HttpRequest* req)
{
    if (sockfd < 0 || req == NULL)
    {
        return;
    }

    HttpResponse response;
    response.SetHttpVersion(req->GetVersion());

    if (req->GetMethod() != GET)
    {
        SetAndWriteBack(sockfd, response, "400", "Bad Request");
        return;
    }

    string url = _rootPath + req->GetUrl();
    int fd = open(url.c_str(), O_RDONLY);
    if (fd < 0)
    {
        SetAndWriteBack(sockfd, response, "403", "Forbidden");
        return;
    }

    struct stat fileInfo;
    memset(&fileInfo, 0, sizeof(struct stat));

    if (fstat(fd, &fileInfo) < 0
        || fileInfo.st_size > ConfManager::Instance()->GetMaxFileSize())
    {
        SetAndWriteBack(sockfd, response, "500", "Internal Server Error");
        close(fd);

        return;
    }

    int32 size = 0;
    char* data = CreateCStr(fileInfo.st_size);
    if ((size = readn(fd, data, fileInfo.st_size)) < 0)
    {
        SetAndWriteBack(sockfd, response, "500", "Internal Server Error");
        close(fd);

        return;
    }

    string contentType = FileTypes::Instance()->GetType((GetFileExtension(req->GetUrl())));
    SetAndWriteBack(sockfd, response, "200", "OK", contentType, data, size);

    close(fd);
}
